//
// Created by songgf on 25-4-17.
//

#ifndef MAYO_INP_TO_BDF_CONVERT_H
#define MAYO_INP_TO_BDF_CONVERT_H

#include "convertor.h"

#include "convertor.h"
#include <iomanip>
#include <map>
#include <regex>
#include <string>
#include <vector>

class InpToBdfConvertor : public Convertor {
public:
  InpToBdfConvertor() = default;
  virtual ~InpToBdfConvertor() = default;
  virtual int convert(const std::string &inpPath,
                      const std::string &bdfPath) override;

private:
  struct Node {
    int id;
    double x;
    double y;
    double z;
  };

  struct Element {
    int id;
    std::string type;
    int propertyId = 0;
    std::vector<int> nodeIds;

    Element() = default;

    Element(int id, const std::string &type, const std::vector<int> &nodeIds)
        : id(id), type(type), nodeIds(nodeIds) {}
  };

  struct Elset {
    std::string id;
    std::vector<int> elemIds;
    std::string materialId;
    double thickness = 1.0;
  };

  struct NodeSet {
    std::string id;           // NSET的名字
    std::vector<int> nodeIds; // 这个节点集里有哪些 node ID
  };

  struct Material {
    std::string id;
    double E = 0.0;  // 弹性模量
    double G = 0.0;  // 剪切模量
    double nu = 0.0; // 泊松比
    double rho;      // 密度
    double alpha;    //  热膨胀系数
  };

  int parseInpFile(const std::string &path);
  void parseNode(const std::string &line);
  void parseElement(const std::string &line, const std::string &elemType);
  void parseElset(const std::string &line,
                  std::map<std::string, std::string> parameters);
  void parseShellSection(const std::string &line, const std::string &elsetId,
                         const std::string &materialId);
  std::string parseElemType(const std::string &line);
  int generateBdfFile(const std::string &path);
  std::string mapToBdfElementType(const std::string &inpType);

  void trim(std::string &s);
  std::map<std::string, std::string> getParamMap(const std::string &line);
  int extractTrailingDigits(const std::string &str);
  void parseElastic(const std::string &line, const std::string &materialId);
  void writeCHEXA(std::ofstream &out, const Element &elem);
  void writeMAT1(std::ofstream &out, const Material &mat);
  std::string toUpperCopy(const std::string &input);
  void parseElementBlock(std::istream &in, const std::string &elemType);

private:
  std::vector<Node> nodes;
  std::vector<Element> elements;
  std::vector<Elset> elsets;
  std::map<int, int> elementTypeMap;
  std::vector<NodeSet> nodeSets;
  std::map<std::string, Material> materials;
};

#endif // MAYO_INP_TO_BDF_CONVERT_H
